eval(loadFile("main/src/viz.js"));

var graphics;
var screen;

testCases(test,
    function setUp() {
        graphics = {};
        screen = {};
    },

    function shouldBuildSlideFromEventBySlideFactorySpecifiedInTypeField() {
        var event = {type : "slideFactory"};

        viz.slideFactory = assert.functionThatMustBeCalled("slideFactory", function (screen, slideEvent) {
            assert.that(slideEvent, eq(event));
        });
        viz.slides(screen, [event]);
    },

    function shouldAddFrameAssetAtScreenForGivenSlide() {
        var firstSlideFrameAsset = {};
        viz.slideFactory = function (screen, slideEvent) {
            screen.addFrameAsset(firstSlideFrameAsset);
        };

        screen.addFrameAsset = assert.functionThatMustBeCalled("addFrameAsset", function (slideIndex, frameAsset) {
            assert.that(slideIndex, eq(0));
            assert.that(frameAsset, eq(firstSlideFrameAsset));
        });
        viz.slides(screen, [{type : "slideFactory"}]);
    },

    function shouldPlaceFrameAssetAfterAnotherAtScreenForGivenSlide() {
        var firstSlideFrameAsset = {};
        var anotherFrameAsset = {};
        viz.slideFactory = function (screen, slideEvent) {
            screen.placeFrameAsset(firstSlideFrameAsset).after(anotherFrameAsset);
        };

        var coordinate = {};
        coordinate.placedAfter = assert.functionThatMustBeCalled("placedAfter", function (frameAsset) {
            assert.that(frameAsset, eq(anotherFrameAsset));
        });
        screen.placeFrameAsset = assert.functionThatMustBeCalled("placeFrameAsset", function (slideIndex, frameAsset) {
            assert.that(slideIndex, eq(0));
            assert.that(frameAsset, eq(firstSlideFrameAsset));
            return coordinate;
        });
        viz.slides(screen, [{type : "slideFactory"}]);
    },

    function shouldDrawFrameAssetsFromFirstSlideWhenFirstSlideIsProjected() {
        viz.slideFactory = function (screen, slideEvent) {
            return {};
        };
        var slides = viz.slides(screen, [{type : "slideFactory"}]);

        screen.drawFrameAssets = assert.functionThatMustBeCalled("drawFrameAssets", function (currentSlide, graphics) {
            assert.that(currentSlide, eq(0));
        });
        slides.project(graphics);
    },

    function shouldMoveToNextSlideToProject() {
        var firstSlide = {};
        var secondSlide = {};
        viz.slideFactory = function (screen, slideEvent) {
            return slideEvent.slide;
        };
        var slides = viz.slides(screen, [{type : "slideFactory", slide : firstSlide}, {type : "slideFactory", slide : secondSlide}]);

        firstSlide.lastFrame = assert.functionThatMustBeCalled("lastFrame");
        secondSlide.firstFrame = assert.functionThatMustBeCalled("firstFrame");
        slides.nextSlide();

        screen.drawFrameAssets = assert.functionThatMustBeCalled("drawFrameAssets", function (currentSlide, graphics) {
            assert.that(currentSlide, eq(1));
        });
        slides.project(graphics);
    },

    function shouldMoveToPreviousSlideToProject() {
        var firstSlide = {lastFrame : function () {}};
        var secondSlide = {firstFrame : function () {}, lastFrame : function () {}};
        var thirdSlide = {firstFrame : function () {}};
        viz.slideFactory = function (screen, slideEvent) {
            return slideEvent.slide;
        };
        var slides = viz.slides(screen, [
            {type : "slideFactory", slide : firstSlide},
            {type : "slideFactory", slide : secondSlide},
            {type : "slideFactory", slide : thirdSlide}
        ]);

        slides.nextSlide();
        slides.nextSlide();

        firstSlide.lastFrame = assert.functionThatMustBeCalled("lastFrame");
        secondSlide.firstFrame = assert.functionThatMustBeCalled("firstFrame");
        slides.previousSlide();

        screen.drawFrameAssets = assert.functionThatMustBeCalled("drawFrameAssets", function (currentSlide, graphics) {
            assert.that(currentSlide, eq(1));
        });
        slides.project(graphics);
    },

    function shouldMoveToNextFrameWhenNextFrameExists() {
        var slide = {};
        viz.slideFactory = function (screen, slideEvent) {
            return slide;
        };
        var slides = viz.slides(screen, [{type : "slideFactory"}]);

        slide.isLastFrame = assert.functionThatMustBeCalled("isLastFrame", function () {
            return false;
        });
        slide.nextFrame = assert.functionThatMustBeCalled("nextFrame");
        slides.nextFrame();
    },

    function shouldNotMoveToNextFrameWhenNextFrameDoesNotExist() {
        var slide = {};
        viz.slideFactory = function (screen, slideEvent) {
            return slide;
        };
        var slides = viz.slides(screen, [{type : "slideFactory"}]);

        slide.isLastFrame = assert.functionThatMustBeCalled("isLastFrame", function () {
            return true;
        });
        slide.nextFrame = assert.functionThatMustNotBeCalled("nextFrame");
        slides.nextFrame();
    },

    function shouldSetSizeOfGraphicsWithCollectiveSizeFromFrameAssetsWhenInitialised() {
        var slides = viz.slides(screen, []);

        screen.width = assert.functionThatMustBeCalled("width", function (graphics) {
            return 100;
        });
        screen.height = assert.functionThatMustBeCalled("height", function (graphics) {
            return 200;
        });
        graphics.size = assert.functionThatMustBeCalled("size", function (width, height) {
            assert.that(width, eq(100));
            assert.that(height, eq(200));
        });
        slides.init(graphics);
    }
);